package com.example.database.demo.controller;

import com.example.database.demo.enums.ExpressServiceCodeEnum;
import com.example.database.demo.pojo.Result;
import com.example.database.demo.pojo.SFPojo.requestData.ListFreightQuery.ListFreightQuery;
import com.example.database.demo.pojo.SFPojo.requestData.OrderCancel.OrderCancel;
import com.example.database.demo.pojo.SFPojo.requestData.OrderResultQuery.OrderResultQuery;
import com.example.database.demo.pojo.SFPojo.requestData.PlaceOrder.RequestParms;
import com.example.database.demo.pojo.SFPojo.requestData.PrintWayBills.PrintWayBills;
import com.example.database.demo.pojo.SFPojo.requestData.PrintWayBillsForSync.PrintWayBillsForSync;
import com.example.database.demo.pojo.SFPojo.requestData.PushOrderState.PushOrderState;
import com.example.database.demo.pojo.SFPojo.requestData.RouteQuery.RouteQuery;
import com.example.database.demo.pojo.SFPojo.responseData.ResponseData;
import com.example.database.demo.service.SFPhysicalPublicService;
import com.example.database.demo.utils.PdfFileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import static com.example.database.demo.config.SnowflakeConfig.generateUniqueId;
import static com.example.database.demo.constants.SFContestant.expressFileNameSuffix;


/**
 * @author 梅芙雨Vanessa
 */
@RestController
@CrossOrigin
@Slf4j
public class PlaceOrderController {
    @Value("${SF.PDF_DOWNLOAD_DIRECTORY}")
    public String pdfDownLoadDirectory;
    @Value("${SF.PDF_FIleURL}")
    public String PDF_FIleURL;
    @Autowired
    private SFPhysicalPublicService publicService;

    /**
     * 下订单的接口
     */
    @RequestMapping(value = "/placeOrder", method = RequestMethod.POST)
    public List<ResponseData> placeOrder(@RequestBody @Validated List<RequestParms> requestParams) throws IOException {
        return publicService.placeOrder(requestParams, ExpressServiceCodeEnum.EXP_RECE_CREATE_ORDER.getCode());
    }

    /**
     * 订单查询接口
     */
    @RequestMapping(value = "/orderResultQuery", method = RequestMethod.POST)
    public List<ResponseData> orderResultQuery(@RequestBody @Validated List<OrderResultQuery> orderResultQuery) throws IOException {
        return publicService.orderResultQuery(orderResultQuery, ExpressServiceCodeEnum.EXP_RECE_SEARCH_ORDER_RESP.getCode());
    }

    /**
     * 订单取消
     */
    @RequestMapping(value = "/orderCancel", method = RequestMethod.POST)
    public List<ResponseData> orderCancel(@RequestBody @Validated List<OrderCancel> orderCancel) throws IOException {
        return publicService.orderCancel(orderCancel, ExpressServiceCodeEnum.EXP_RECE_UPDATE_ORDER.getCode());
    }

    /**
     * 订单状态回调接口
     */
    @RequestMapping(value = "/PushOrderState", method = RequestMethod.POST)
    public Result PushOrderState(@RequestBody @Validated PushOrderState pushOrderState) throws IOException {
        return publicService.PushOrderState(pushOrderState, ExpressServiceCodeEnum.PushOrderState.getCode());
    }

    /**
     * 路由查询
     */
    @RequestMapping(value = "/routeQuery", method = RequestMethod.POST)
    public ResponseData routeQuery(@RequestBody @Validated RouteQuery routeQuery) throws Exception {
        return publicService.routeQuery(routeQuery, ExpressServiceCodeEnum.EXP_RECE_SEARCH_ROUTES.getCode());
    }

    /**
     * 清单运费查询接口
     */
    @RequestMapping(value = "/listFreightQuery", method = RequestMethod.POST)
    public List<ResponseData> listFreightQuery(@RequestBody @Validated List<ListFreightQuery> listFreightQuery) throws IOException {
        return publicService.listFreightQuery(listFreightQuery, ExpressServiceCodeEnum.EXP_RECE_QUERY_SFWAYBILL.getCode());
    }

    /**
     * 清单运费查询接口推送接口
     */
    @RequestMapping(value = "/pushListFreightQuery", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    public Result pushListFreightQuery(@RequestParam("sign") String sign, @RequestParam("content") String content) throws IOException {
        return publicService.pushListFreightQuery(content);
    }

    /**
     * 面单查询打印同步功能
     */
    @RequestMapping(value = "/printWayBills", method = RequestMethod.POST)
    public List<ResponseData> printWayBills(@RequestBody @Validated List<PrintWayBills> printWayBills) throws IOException {
        return publicService.printWayBills(printWayBills, ExpressServiceCodeEnum.COM_RECE_CLOUD_PRINT_WAYBILLS.getCode());
    }

    /**
     * 面单异步查询打印功能
     */
    @RequestMapping(value = "/printWayBillsForSync", method = RequestMethod.POST)
    public ResponseData printWayBillsForSync(@RequestBody @Validated PrintWayBillsForSync printWayBillsForSync) throws IOException {
        return publicService.printWayBillsForSync(printWayBillsForSync, ExpressServiceCodeEnum.COM_PUSH_CLOUD_PRINT_WAYBILLS.getCode());
    }

    /**
     * 面单下载功能
     */
    @RequestMapping(value = "/downLoadPrintWayBills", method = RequestMethod.POST)
    public ResponseEntity<byte[]> downLoadPrintWayBills(@RequestBody List<String> waybillNoList) throws Exception {
        return publicService.downLoadPrintWayBills(waybillNoList);
    }

    @GetMapping("/downloadPdf")
    public ResponseEntity<byte[]> downloadPdf(String waybillNo) throws IOException {
        String fileName = waybillNo + expressFileNameSuffix;
        Path pdfPath = Paths.get(pdfDownLoadDirectory + fileName);
        byte[] pdfBytes = Files.readAllBytes(pdfPath);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_PDF);
        headers.setContentDispositionFormData("attachment", pdfPath.getFileName().toString());
        return ResponseEntity.ok().headers(headers).contentLength(pdfBytes.length).body(pdfBytes);
    }

    @GetMapping("/getPdf")
    public String getPdf(String waybillNo) throws IOException {
        File file = new File(pdfDownLoadDirectory + waybillNo + expressFileNameSuffix);
        return file.toURI().toString();
    }

    @GetMapping("/pdf/{waybillNo}")
    public ResponseEntity<Resource> getResource(@PathVariable String waybillNo) throws MalformedURLException {
        Path pdfPath = Paths.get(pdfDownLoadDirectory).resolve(waybillNo + expressFileNameSuffix);
        Resource pdfResource = new UrlResource(pdfPath.toUri());
        return ResponseEntity.ok().contentType(MediaType.valueOf("application/pdf")).header(HttpHeaders.CONTENT_DISPOSITION, "inline;filename=" + pdfResource.getFilename()).body(pdfResource);
    }

    @GetMapping(value = "/getPdf/{waybillNo}", produces = {MediaType.MULTIPART_FORM_DATA_VALUE})
    public byte[] getFileWithMediaType(@PathVariable("waybillNo") String waybillNo) throws IOException {
        File file = new File(pdfDownLoadDirectory + waybillNo + expressFileNameSuffix);
        return IOUtils.toByteArray(Files.newInputStream(file.toPath()));
    }

    @PostMapping(value = "/mergePdf")
    public ResponseEntity<String> getFileWithMediaType(@RequestBody List<String> pdfFileList) throws IOException {
        File mergedFile = PdfFileUtil.mergeFiles(pdfFileList, generateUniqueId());
        // 确保目录存在
        Files.createDirectories(Paths.get(pdfDownLoadDirectory));
        // 将文件保存到指定目录
        File destination = new File(pdfDownLoadDirectory + mergedFile.getName() + expressFileNameSuffix);
        Files.copy(mergedFile.toPath(), destination.toPath());
        Files.deleteIfExists(mergedFile.toPath());
        // 构造文件的 HTTP URL
        String fileUrl = PDF_FIleURL + destination.getName().replace(expressFileNameSuffix, "");
        return ResponseEntity.ok().contentType(MediaType.valueOf("application/pdf")).header(HttpHeaders.CONTENT_DISPOSITION, "inline;filename=" + destination.getName()).body(fileUrl);
    }
}
